using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using Firestarter.DB.Schema.BO;
using Firestarter.DB.Schema.Logic;
using Firestarter.DB.Schema.Test.BO.TestUtils;
using Firestarter.DB.Schema.Test.Logic.DBMerge;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using Habanero.BO.Loaders;
using Habanero.Testability;
using NUnit.Framework;

namespace Firestarter.DB.Schema.Test.Logic
{
    [TestFixture]
    public class TestMergeDBColumn
    {
        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            ClassDef.ClassDefs.Clear();
            string xmlClassDefs = BOBroker.GetClassDefsXml();
            ClassDef.ClassDefs.Add(new XmlClassDefsLoader(xmlClassDefs, new DtdLoader()).LoadClassDefs());
            BORegistry.DataAccessor = new DataAccessorInMemory();

            SchemaMerger.SetupMergeableBORegistry();
        }

        [SetUp]
        public virtual void SetupTest()
        {
        }

        [Test]
        public void Test_MergeDBColumn_ShouldMergeAllProps()
        {
            //---------------Set up test pack-------------------
            DBMergeBO<DBColumn> merger = new DBMergeBO<DBColumn>();
            var fromColumn = TestUtilsDBColumn.CreateUnsavedValidDBColumn();
            fromColumn.IsAutoIncrementing = true;
            fromColumn.Nullable = false;
            var toColumn = new DBColumn();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(fromColumn.ColumnName, toColumn.ColumnName);
            Assert.AreNotEqual(fromColumn.DataType, toColumn.DataType);
            Assert.AreNotEqual(fromColumn.DataLength, toColumn.DataLength);
            Assert.AreNotEqual(fromColumn.Nullable, toColumn.Nullable);
            Assert.AreNotEqual(fromColumn.DefaultValue, toColumn.DefaultValue);
            Assert.AreNotEqual(fromColumn.IsAutoIncrementing, toColumn.IsAutoIncrementing);
            Assert.AreNotEqual(fromColumn.OrdinalPosition, toColumn.OrdinalPosition);
            //---------------Execute Test ----------------------
            merger.MergeBOFrom(fromColumn, toColumn);
            //---------------Test Result -----------------------
            Assert.AreEqual(fromColumn.ColumnName, toColumn.ColumnName);
            Assert.AreEqual(fromColumn.DataType, toColumn.DataType);
            Assert.AreEqual(fromColumn.DataLength, toColumn.DataLength);
            Assert.AreEqual(fromColumn.Nullable, toColumn.Nullable);
            Assert.AreEqual(fromColumn.DefaultValue, toColumn.DefaultValue);
            Assert.AreEqual(fromColumn.IsAutoIncrementing, toColumn.IsAutoIncrementing);
            Assert.AreEqual(fromColumn.OrdinalPosition, toColumn.OrdinalPosition);
        }

        [Test]
        public void Test_MustMergeRelationship_ShouleBeFalseForAllDBColumnRelationships()
        {
            //---------------Set up test pack-------------------
            DBMergeBO<DBColumn> merger = new DBMergeBO<DBColumn>();
            var dbColumn = new DBColumn();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            foreach (var relationship in dbColumn.Relationships)
            {
                Assert.IsFalse(merger.MustMergeRelationship(relationship));   
            }
        }

        [TestCase("ColumnID")]
        [TestCase("Approved")]
        [TestCase("TableID")]
        [TestCase("PendingChangeType")]
        public void Test_MustMergeProp_ShouleBeFalseForColumns(string propName)
        {
            //---------------Set up test pack-------------------
            DBMergeBO<DBColumn> merger = new DBMergeBO<DBColumn>();
            var dbColumn = new DBColumn();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            var boProp = dbColumn.Props[propName];
            var mustMergeProperty = merger.MustMergeProperty(boProp);
            //---------------Test Result -----------------------
            Assert.IsFalse(mustMergeProperty);
        }

        [Test]
        public void Test_MatchFKColumn_WhenNameNotMatch_ShouldNotMatch()
        {
            //---------------Set up test pack-------------------
            DBMergeBO<DBColumn> fkColumnMerger = (DBMergeBO<DBColumn>)MergeableBORegistry.Instance.Resolve<DBColumn>();
            var fromColumn = TestUtilsDBColumn.GetTestFactory()
                .CreateValidBusinessObject();

            var toColumn = TestUtilsDBColumn.GetTestFactory()
                .CreateValidBusinessObject();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(toColumn.ColumnName, fromColumn.ColumnName);
            Assert.AreNotEqual(toColumn.ToString(), fromColumn.ToString());
            //---------------Execute Test ----------------------
            var function = fkColumnMerger.MatchBusinessObject(fromColumn);
            var matchBusinessObject = function(toColumn);
            //---------------Test Result -----------------------
            Assert.IsFalse(matchBusinessObject, "FK Columns should not match");
        }

        [Test]
        public void Test_MatchFKColumn_WhenNameMatch_ShouldMatch()
        {
            //---------------Set up test pack-------------------
            DBMergeBO<DBColumn> fkColumnMerger = (DBMergeBO<DBColumn>)MergeableBORegistry.Instance.Resolve<DBColumn>();
            var fromColumn = TestUtilsDBColumn.GetTestFactory()
                .CreateValidBusinessObject();

            var toColumn = TestUtilsDBColumn.GetTestFactory()
                .WithValue(column => column.ColumnName, fromColumn.ColumnName)
                .CreateValidBusinessObject();
            //---------------Assert Precondition----------------
            Assert.AreEqual(toColumn.ColumnName, fromColumn.ColumnName);
            Assert.AreEqual(toColumn.ToString(), fromColumn.ToString());
            //---------------Execute Test ----------------------
            var function = fkColumnMerger.MatchBusinessObject(fromColumn);
            var matchBusinessObject = function(toColumn);
            //---------------Test Result -----------------------
            Assert.IsTrue(matchBusinessObject, "FK Columns should not match");
        }
        [Test]
        public void Test_MatchFKColumn_WhenNameMatch_ButTableNotMatch_ShouldMatch()
        {
            //---------------Set up test pack-------------------
            DBMergeBO<DBColumn> fkColumnMerger = (DBMergeBO<DBColumn>)MergeableBORegistry.Instance.Resolve<DBColumn>();
            var fromColumn = TestUtilsDBColumn.GetTestFactory()
                .WithValueFor(dbColumn => dbColumn.Table)
                .CreateValidBusinessObject();

            var toColumn = TestUtilsDBColumn.GetTestFactory()
                .WithValueFor(dbColumn => dbColumn.Table)
                .WithValue(column => column.ColumnName, fromColumn.ColumnName)
                .CreateValidBusinessObject();
            //---------------Assert Precondition----------------
            Assert.AreEqual(toColumn.ColumnName, fromColumn.ColumnName);
            Assert.AreNotEqual(toColumn.TableName, fromColumn.TableName); ;
            Assert.AreNotEqual(toColumn.ToString(), fromColumn.ToString());
            //---------------Execute Test ----------------------
            var function = fkColumnMerger.MatchBusinessObject(fromColumn);
            var matchBusinessObject = function(toColumn);
            //---------------Test Result -----------------------
            Assert.IsTrue(matchBusinessObject, "FK Columns should not match");
        }
    }
}